using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace mp.Scanner
{
	public class Scanner
	{		
		// -- Constructor for the scanner class
		public Scanner()
		{
			fsa = new FSAs();
		}
		
		//	-- pre:  The file given as an input string exists.
		//  -- post: The file has been opened as a positioningReader.
		//  --       Variable filename is the name of the file to be opened
		public bool OpenFile(string filename)
		{
			if(File.Exists(filename))
			{
				FileStream fs = File.OpenRead(filename);	
				posReader = new PositioningReader(new StreamReader(fs));
			}
			else
			{
				Console.WriteLine("File Does not exist\n");
				return false;
			}
			
			return true;
		}
		
		//	-- pre:  The input file pointer is pointing at the first character after the last token scanned.
		//  -- post: The input file pointer is pointing at the first character after the current token.
		//  --       Variable currentToken contains the name of the token scanned
		//  --       Variable Lexeme contains the string that was matched as the token was scanned.
		//  --       Variable startLine contains the line number in the source code where the current token starts
		//  --       Variable startCol contains the column number in the source code line where the current token starts
		public string GetToken()
		{
			int currentChar = posReader.Peek();
			string currentToken;
			
			//Skip White Space
			while((char)currentChar == '\r' ||(char)currentChar == ' ' || (char)currentChar == '\n' || (char)currentChar == '\t' || (char)currentChar == '{')
			{
				if((char)currentChar == '{')
				{
					currentToken = fsa.Scan_Comment(posReader);
					if(currentToken == Token.mp_run_comment)
					{
						return currentToken;
					}
				}
				else {
					posReader.Read();
				}
				currentChar = posReader.Peek();
			}
			
			startCol = posReader.CharPos;
			startLine = posReader.LinePos;
			
			if(currentChar < 0){
				currentToken = fsa.Scan_EOF(posReader);
			}
			else if(Char.IsLetter((char)currentChar))
			{
				currentToken = fsa.Scan_Identifier(posReader);
			}
			else if(Char.IsDigit((char)currentChar))
			{
				currentToken = fsa.Scan_Number(posReader);
			}
			else {
				switch(currentChar){				
					case ',':
						currentToken = fsa.Scan_Comma(posReader);
						break;
					case ';':
						currentToken = fsa.Scan_Scolon(posReader);
						break;
					case '(':
						currentToken = fsa.Scan_LParen(posReader);
						break;
					case ')':
						currentToken = fsa.Scan_RParen(posReader);
						break;
					case '=':
						currentToken = fsa.Scan_Equal(posReader);
						break;
					case '>':
						currentToken = fsa.Scan_GEqual(posReader);
						break;
					case '<':
						currentToken = fsa.Scan_LEqual(posReader);
						break;
					case ':':
						currentToken = fsa.Scan_Assign(posReader);
						break;
					case '+':
						currentToken = fsa.Scan_Plus(posReader);
						break;
					case '-':
						currentToken = fsa.Scan_Minus(posReader);
						break;
					case '*':
						currentToken = fsa.Scan_Times(posReader);
						break;
					case '.':
						currentToken = fsa.Scan_Period(posReader);
						break;
					default:
						currentToken = Token.mp_error;
						fsa.currentLexeme = "" + (char) posReader.Read();
						break;
				}
			}

			return currentToken;
		}
		
		//	-- pre:  A token has already been scanned
		//  -- post: The actual lexeme that was scanned in the most recent call to getToken()
		public string GetLexeme()
		{
			return fsa.currentLexeme;
		}
		
		//	-- pre:  A token has already been scanned
		//  -- post: The starting line of the token found for the that most recent call to getToken()
		public int GetLine()
		{
			return startLine;
		}
		
		//	-- pre:  A token has already been scanned
		//  -- post: The starting column of the token found for the that most recent call to getToken()
		public int GetColumn()
		{
			return startCol;
		}
		
		#region properties
		
		int startCol = 0;  //holder for the starting column
		int startLine = 0;  //holder for the starting row
		private PositioningReader posReader; //the positioning reader that is open when open file is called
		private FSAs fsa;  //FSAs that are called when a particular char is found
		
		#endregion properties
	}
}

